package aiP.A3.Client.Monitor;

import aiP.A3.Client.Dispatcher.Dispatcher;
import aiP.A3.Client.GUI.Dashboard.Dashboard_Gui;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: Andreas
 * Date: 16.05.14
 * Time: 09:37
 * To change this template use File | Settings | File Templates.
 */
public class Monitor {

    private Map<String, Instance> instanzen = null;
    public static final int SERVER_PORT = 1174;                                // max port-value = 65535
    public static final int INSTANCE_CHECK_TIME = 300;
    public static final int INSTANCE_LIFETIME = 250;


    private Dashboard_Gui dashboard = new Dashboard_Gui(this);
    private Date now;                                                           // Zeitstempel für Log Ausgaben
    private SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss");  // Zeitstempel formatieren
    private DeadInstanceThread deadInstanceThread;
    private MonitorThread mThread = null;
    /**
     * Konstruktor
     */
    public Monitor() throws RemoteException, NotBoundException, InterruptedException {

        instanzen = new HashMap<String, Instance>();
        starteMonitorThread(this);
        System.out.println("nach monitorThread");
        deadInstanceThread = new DeadInstanceThread(this);
        deadInstanceThread.start();
        System.out.println("nach DeadInstanceThread");

        // Dashboard erstellen. Als Parameter muss der Monitor übergeben werden
        System.out.println("vor dashboard");
        System.out.println("nach dashboard");
    }

    public MonitorThread getmThread() {
        return mThread;
    }

    private void starteMonitorThread(Monitor monitor){
        mThread = new MonitorThread(monitor);
        mThread.start();
    }

    public void stoppeMonitorThread(){
        if(mThread.isAlive())
        mThread.toeten();
    }

    /**
     * Liste aller Instanzen zurückgeben
     *
     * @return Liste aller Instanzen
     */
    public List<Instance> getInstanzen() {
        List<Instance> erg = new ArrayList<Instance>();
        erg.addAll(instanzen.values());
        //System.out.println("instanzenListe länge:"+ erg.size());
        return erg;
    }

    public Dashboard_Gui getDashboard(){
        return dashboard;
    }

    public synchronized Map<String, Instance> getInstanzenMap() {
        return instanzen;
    }

    public void log_in_Dashboard(String text){
        dashboard.logMessage(text);
    }

    /**
     * Liste der lebenden Instanzen zurückgeben
     *
     * @return Liste der lebenden Instanzen
     */
    public List<Instance> getLebendeInstazen() {
        List<Instance> erg = new ArrayList<Instance>();
        for (Instance instance : getInstanzen()) {
            erg.add(instance);
        }
        return erg;
    }

    /**
     * Instanz zu der Liste aller Instanzen (tot und lebendig hinzufügen)
     *
     * @param instance
     */
    public synchronized void addInstanz(Instance instance) {
        instanzen.put(instance.getId(), instance);
        System.out.println(" Instance: " +  instance + " Map: " + instanzen + " Size: " + instanzen.size());
        switch (instanzen.size()){
            case 1:
                    dashboard.setInstance_I(instance);
                    break;
            case 2:
                    dashboard.setInstance_II(instance);
                    break;
        }
        dashboard.chanceStatus(true, instanzen.size());
        dashboard.logMessage(instance.toString());
    }

//    public synchronized void removeInstanzByID(String id) {
//        if (instanzen.containsKey(id) ) {
//            instanzen.remove(id);
//        }
//
//    }

    /**
     * Starten/ Erwachen einer ServerInstance
     *
     * @param serverInstance
     */
    public void awake(String serverInstance) throws RemoteException, NotBoundException {
        System.out.println(""+ serverInstance);
        Instance instance = instanzen.get(String.valueOf(serverInstance));
        System.out.println("instanzen.get: "+ instanzen.get(String.valueOf(serverInstance)).toString());
        instance.setLebendig();
        instance.start();
        instance.getInstance().setAlive(true);

        System.out.println("instanz " + instance.getId() + " ist tot: " + instance.isTot());
        instanzen.put(instance.getId(), instance);
        System.out.println("aus  ONOFF: " + instanzen.get(String.valueOf(serverInstance)).isLebendig());
        deadInstanceThread.clearInstance(instance);
        now = new Date();
        dashboard.logMessage(dateFormatter.format(now) + ": Instanz " + instance.getId() + " ist lebendig");
    }

    /**
     * Schließen einer ServerInstance
     *
     * @param serverInstance
     */
    public void shutDown(String serverInstance) throws RemoteException, NotBoundException {
        Instance instance = instanzen.get(String.valueOf(serverInstance));
        instance.setTot();
        instance.stop();
        instance.getInstance().setAlive(false);

        System.out.println("instanz " + instance.getId() + " ist lebendig: " + instance.isLebendig());
        instanzen.put(instance.getId(), instance);
        System.out.println("aus  ONOFF: " + instanzen.get(String.valueOf(serverInstance)).isLebendig());

        now = new Date();
        dashboard.logMessage(dateFormatter.format(now) + ": Instanz " + instance.getId() + " ist nicht mehr lebendig");
        //removeInstanzByID(instance.getId());
    }




    public void printInstanzStatusOnlineTime() {
        List<Instance> temp = new ArrayList<Instance>();
        temp.addAll(instanzen.values());

        for(Instance inst : temp) {
            now = new Date();
            dashboard.logMessage(dateFormatter.format(now) + " " + inst.toString());
        }
    }
}